fix: 使用原子写入防止重启时配置丢失#233
Merged
chenjintang-shrimp merged 12 commits intoMay 16, 2026
Merged
Conversation
确保抽奖结果中的学生ID能够正确从候选数据中提取并传递到奖品信息中 同时修正抽奖结果显示时学生ID的获取逻辑
当无法附加到共享内存时,增加服务器状态检测和资源清理逻辑 修复本地服务器启动失败时未清理残留socket的问题
在POSIX系统上,QSharedMemory在进程崩溃后不会自动清理残留的共享内存段 添加_cleanup_stale_shared_memory函数来检测并清理这些残留资源
修复服务器无响应检查的描述不准确问题,改为更明确的"服务器不可连接" 改进奖品ID处理逻辑,增加异常捕获和多种ID字段尝试
通过ruff移除未使用的time导入
统一文档中的换行格式,移除多余的空格
问题:重启(正常或异常)后再次启动可能弹出程序 OOBE,原有配置丢失。 原因:settings.json 等配置文件使用非原子写入(open + json.dump), 当系统在写入过程中崩溃或断电时,文件会被截断或损坏,导致应用 启动时将损坏的配置文件视为空配置,重新创建默认设置并触发 OOBE。 修复: 1. 在 path_utils.py 中新增 atomic_write_json() 和 atomic_write_bytes() 工具函数,采用 tempfile + os.replace() 原子写入模式,确保写入 过程中崩溃不会损坏目标文件 2. 将 settings_access.py、settings_default.py、config.py、 secure_store.py、file_utils.py 中所有关键配置文件的写入操作 替换为原子写入 3. 在 settings_default.py 的 manage_settings_file() 中增加备份恢复 机制:当 settings.json 损坏时,优先从最近的备份 zip 中恢复配置, 仅在无可用备份时才回退到默认值 Closes SECTL#231
chenjintang-shrimp
approved these changes
May 15, 2026
Comment on lines
+149
to
+167
| except Exception as e: | ||
| logger.warning(f"写入安全配置失败:{p}, 错误:{e}") | ||
| try: | ||
| import tempfile | ||
|
|
||
| with tempfile.NamedTemporaryFile( | ||
| mode="wb", delete=False, dir=os.path.dirname(p) | ||
| ) as tmp_file: | ||
| tmp_file.write(b"SRV1" + payload) | ||
| tmp_path = tmp_file.name | ||
|
|
||
| # 替换原文件 | ||
| os.replace(tmp_path, p) | ||
| raw = json.dumps(d, ensure_ascii=False, indent=4).encode("utf-8") | ||
| comp = zlib.compress(raw, level=6) | ||
| key = _platform_key() | ||
| payload = _encrypt_payload(comp, key) | ||
| with open(p, "wb") as f: | ||
| f.write(b"SRV1" + payload) | ||
| _set_hidden(str(p)) | ||
| logger.debug(f"使用临时文件写入安全配置成功:{p}") | ||
| except Exception as temp_e: | ||
| logger.warning(f"使用临时文件写入安全配置也失败:{temp_e}") | ||
| # 降级到明文JSON写入 | ||
| logger.debug(f"降级直接写入安全配置成功:{p}") | ||
| except Exception as e2: | ||
| logger.warning(f"降级写入安全配置也失败:{e2}") | ||
| try: | ||
| with open(p, "w", encoding="utf-8") as f: | ||
| json.dump(d, f, ensure_ascii=False, indent=4) | ||
| logger.warning(f"写入安全配置降级为明文JSON:{p}") | ||
| except Exception as e2: | ||
| logger.warning(f"降级写入明文JSON也失败:{e2}") | ||
| except Exception as e3: | ||
| logger.warning(f"降级写入明文JSON也失败:{e3}") |
Contributor
There was a problem hiding this comment.
这里其实有个跟这个patch不太相关的点,就是说,你的当前实现都是三次对同一个文件写入……
问题在于,当加密配置文件被占用,按照Python的性能估计,这三个backup全炸,全都是epermdenied,根本就没有回旋余地,其他的settings.json同理,所以考虑是否提示用户解决权限问题?
Contributor
|
@sourcery-ai review |
|
Hi @chenjintang-shrimp! 👋 Only authors and team members can run @sourcery-ai commands on public repos. If you are a team member, install the @sourcery-ai bot to get access ✨ |
Contributor
|
@trustedinster 请先解决合并冲突,解决完毕后我会合并 |
1. 修复 Sentry 建议:备份恢复后不再直接 return, 而是将恢复数据赋给 current_settings 继续执行 schema merge 和 ensure_device_uuid() 2. 简化 secure_store.py 降级链:移除三次写同一文件的 无意义降级,改为在 PermissionError 时明确提示用户 解决权限问题 3. 解决与 upstream/master 的合并冲突
chenjintang-shrimp
approved these changes
May 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
Closes #231
重启(正常或异常)后再次启动可能弹出程序 OOBE,原有配置丢失。
根因分析
settings.json等配置文件使用非原子写入(open("w")+json.dump()),当系统在写入过程中崩溃或断电时,文件会被截断或损坏。应用启动时检测到损坏的配置文件,将其视为空配置,重新创建默认设置并触发 OOBE。修复内容
1. 新增原子写入工具函数(
path_utils.py)atomic_write_json()— 原子写入 JSON 文件atomic_write_bytes()— 原子写入二进制文件采用
tempfile.mkstemp()+os.replace()模式:os.replace()原子替换目标文件f.flush()+os.fsync()确保数据落盘os.replace()是原子操作;Windows NTFS 上也是近似原子的2. 替换所有关键配置文件的非原子写入
settings_access.pyupdate_settings()open+json.dump→atomic_write_jsonsettings_default.pymanage_settings_file()settings_default.pyensure_device_uuid()config.pyimport_settings()config.py_save_drawn_records()secure_store.pywrite_secrets()atomic_write_bytes,保留降级逻辑secure_store.pywrite_behind_scenes_settings()file_utils.pysave_history_data()3. 新增备份恢复机制(
settings_default.py)新增
_try_recover_settings_from_backup()函数:当settings.json损坏时,优先从最近的备份 zip 中恢复配置,仅在无可用备份时才回退到默认值。测试
ruff check全部通过